home *** CD-ROM | disk | FTP | other *** search
/ Aminet 28 / Aminet 28 (1998)(GTI - Schatztruhe)[!][Dec 1998].iso / Aminet / dev / src / GLperf3.12-src.lha / GLperf / QuadStrp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-01  |  12.1 KB  |  368 lines

  1. /*
  2. //   (C) COPYRIGHT International Business Machines Corp. 1993
  3. //   All Rights Reserved
  4. //   Licensed Materials - Property of IBM
  5. //   US Government Users Restricted Rights - Use, duplication or
  6. //   disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  7. //
  8.  
  9. //
  10. // Permission to use, copy, modify, and distribute this software and its
  11. // documentation for any purpose and without fee is hereby granted, provided
  12. // that the above copyright notice appear in all copies and that both that
  13. // copyright notice and this permission notice appear in supporting
  14. // documentation, and that the name of I.B.M. not be used in advertising
  15. // or publicity pertaining to distribution of the software without specific,
  16. // written prior permission. I.B.M. makes no representations about the
  17. // suitability of this software for any purpose.  It is provided "as is"
  18. // without express or implied warranty.
  19. //
  20. // I.B.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  21. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL I.B.M.
  22. // BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  23. // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  24. // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  25. // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  26. //
  27. // Author:  Barry Minor, IBM AWS Graphics Systems (Austin)
  28. //
  29. */
  30.  
  31. #include <math.h>
  32. #include "QuadStrp.h"
  33.  
  34. #undef offset
  35. #define offset(v) offsetof(QuadStrip,v)
  36.  
  37. static InfoItem QuadStripInfo[] = {
  38. #define INC_REASON INFO_ITEM_ARRAY
  39. #include "QuadStrp.h"
  40. #undef INC_REASON
  41. };
  42. #include <malloc.h>
  43.  
  44. QuadStripPtr new_QuadStrip()
  45. {
  46.     QuadStripPtr this = (QuadStripPtr)malloc(sizeof(QuadStrip));
  47.     CheckMalloc(this);
  48.     new_Polygonal((PolygonalPtr)this);
  49.     SetDefaults((TestPtr)this, QuadStripInfo);
  50.     this->testType = QuadStripTest;
  51.     this->primitiveType = GL_QUAD_STRIP;
  52.     this->vertsPerFacet = 2;
  53.     this->usecPixelPrint = " microseconds per pixel with Quad Strip";
  54.     this->ratePixelPrint = " pixels per second with Quad Strip";
  55.     this->usecPrint = " microseconds per Quad in a Quad Strip";
  56.     this->ratePrint = " Quads per second in a Quad Strip";
  57.     /* Set virtual functions */
  58.     this->delete = delete_QuadStrip;
  59.     this->Layout = QuadStrip__Layout;
  60.     this->Copy = QuadStrip__Copy;
  61.     return this;
  62. }
  63.  
  64. void delete_QuadStrip(TestPtr thisTest)
  65. {
  66.     QuadStripPtr this = (QuadStripPtr)thisTest;
  67.     delete_Polygonal(thisTest);
  68. }
  69.  
  70. TestPtr QuadStrip__Copy(TestPtr thisTest)
  71. {
  72.     QuadStripPtr this = (QuadStripPtr)thisTest;
  73.     QuadStripPtr newQuadStrip = new_QuadStrip();
  74.     FreeStrings((TestPtr)newQuadStrip);
  75.     *newQuadStrip = *this;
  76.     CopyStrings((TestPtr)newQuadStrip, (TestPtr)this);
  77.     return (TestPtr)newQuadStrip;
  78. }
  79.  
  80. static GLfloat* LayoutRandomQStrip(QuadStripPtr this, GLfloat *startingPoint)
  81. {
  82.     GLfloat *strip, *dst;
  83.     GLfloat x0, y0;
  84.     GLfloat x1, y1;
  85.     GLfloat x2, y2;
  86.     int i, j, k;
  87.     int windowDim = min(this->environ.windowWidth, this->environ.windowHeight);
  88.     GLfloat ndcSize = this->size/(GLfloat)windowDim/(GLfloat)windowDim*4.0 / 2.;
  89.     GLfloat distThreshold = sqrt(ndcSize*3.0);
  90.     GLfloat dist;
  91.     GLfloat radius = sqrt(ndcSize*2.0);
  92.     GLfloat random_angle, theta;
  93.     GLfloat t;
  94.     const GLfloat pi=3.141592654;
  95.     const int maxTries = 1000;
  96.     int objsPerBgnEnd = this->objsPerBgnEnd;
  97.  
  98.     /* Here's all the facing and winding stuff */
  99.     int numTries;
  100.     GLfloat initialWinding;
  101.     GLfloat facingFront = this->facingFront;
  102.     GLfloat facingBack  = this->facingBack;
  103.     int numFront, numBack, tmpNum;
  104.     int twistsPerStrip = this->twistsPerStrip;
  105.     int frontTwists, backTwists;
  106.     int numPerFrontTwist, numPerBackTwist;
  107.     int front, back;
  108.     float *winding;
  109.     int face;
  110.  
  111.     /* These are variables for walking the strip */
  112.     int begin, end, firsttry, tenacity;
  113.  
  114.     /* We'll be working with triangles here instead of quads as the
  115.      * triangle strip random walk code was done first and there's no
  116.      * sense in reinventing the wheel, especially with code this complex!
  117.      * The ndcSize used above is divided by 2. to reflect the change into
  118.      * triangles from quads.
  119.      */
  120.  
  121.     /* Figure frontfacing/backfacing stuff */
  122.     if (fabs(1.0 - facingFront - facingBack) > .01) {
  123.         printf("GLperf: FrontFacing + BackFacing not equal to 1\n");
  124.         exit(1);
  125.     }
  126.     numFront = floor((GLfloat)objsPerBgnEnd * facingFront + 0.5);
  127.     numBack = floor((GLfloat)objsPerBgnEnd * facingBack + 0.5);
  128.     numFront += objsPerBgnEnd - numFront - numBack;
  129.     if (numFront >= numBack) {
  130.     /* Start off front facing */
  131.     initialWinding = 1.;
  132.     } else {
  133.     /* Start off back facing */
  134.     initialWinding = -1.;
  135.     /* Reverse front and back numbers (see note below) */
  136.     tmpNum = numFront;
  137.     numFront = numBack;
  138.     numBack = tmpNum;
  139.     }
  140.     /* Note to the reader here:
  141.      * "front" here does not necessarily mean "front-facing", but
  142.      * merely the direction that the triangles are facing when the
  143.      * strip starts.  Conversely, "back" does not mean "back-facing",
  144.      * but is the opposite direction of the strip's initial facing.
  145.      * It's confusing, but it makes the loop simpler below.
  146.      */
  147.     frontTwists = (twistsPerStrip + 2) / 2;
  148.     backTwists  = (twistsPerStrip + 1) / 2;
  149.     if (numFront < frontTwists || numBack < backTwists) {
  150.     printf("GLperf: So many twists per strip... so few triangles.\n");
  151.     exit(1);
  152.     }
  153.     numPerFrontTwist = (numFront + frontTwists - 1) / frontTwists;
  154.     if (backTwists != 0)
  155.         numPerBackTwist = (numBack + backTwists - 1) / backTwists;
  156.     else
  157.         numPerBackTwist = 0;
  158.  
  159.     /* Allocate necessary data */
  160.     strip = (GLfloat*)malloc(this->vertsPerBgnEnd * 2 * sizeof(GLfloat));
  161.     CheckMalloc(strip);
  162.     dst = strip;
  163.  
  164.     /* Pull x, y, and z from startingPoint */
  165.     x0 = *startingPoint++;
  166.     y0 = *startingPoint++;
  167.     *dst++ = x0;
  168.     *dst++ = y0;
  169.  
  170.     /* Find second point within a certain radius of the startingPoint */
  171.     do {
  172.         random_angle = 2.0*pi*(GLfloat)myrand()/(GLfloat)MY_RAND_MAX;
  173.         x1 = x0 + radius * cos(random_angle);
  174.         y1 = y0 + radius * sin(random_angle);
  175.     } while (x1 <= -1.0 || 1.0 <= x1 || y1 <= -1.0 || 1.0 <= y1);
  176.     *dst++ = x1;
  177.     *dst++ = y1;
  178.  
  179.     front = 0;
  180.     back = 0;
  181.     /* Determine the winding for all the triangles in advance and store
  182.      * in the "winding" array (FRONT is 1) (BACK is -1).
  183.      * This makes the loop quite a bit easier to manage.
  184.      */
  185.     winding = (float*)malloc((this->twistsPerStrip+1) * numFront * 2 * sizeof(float));
  186.     face = initialWinding;
  187.     k = 0;
  188.     for (i=0; i<twistsPerStrip+1; i++) {
  189.     for (j=0; j < ((i&1) ? numPerBackTwist : numPerFrontTwist); j++) {
  190.         winding[k] = face * ((k&1) ? -1. : 1.);
  191.         winding[k+1] = face * ((k&1) ? 1. : -1.);
  192.         k += 2;
  193.     }
  194.     face *= -1;
  195.     }
  196.     /* objsPerBgnEnd must double to reflect our working in triangles rather
  197.      * than quads
  198.      */
  199.     objsPerBgnEnd *= 2;
  200.  
  201.     begin = 0;
  202.     end = objsPerBgnEnd;
  203.     tenacity = maxTries;
  204.     firsttry = 1;
  205.     do {
  206.         for (i=begin; i<end; i++) {
  207.         /* Find a point to create the next triangle in the strip */
  208.             numTries = 0;
  209.             do {
  210.                 random_angle = pi * (GLfloat)myrand()/(GLfloat)MY_RAND_MAX;
  211.                 theta = random_angle - atan2(y1 - y0, x1 - x0);
  212.                 while (theta<0.0) theta+=2.*pi;
  213.                 while (theta>2.*pi) theta-=2.*pi;
  214.                 t = winding[i] * 2. * ndcSize / 
  215.                     (cos(theta)*(y0 - y1) - sin(theta)*(x0 - x1));
  216.                 x2 = t * cos(theta) + x1;
  217.                 y2 = t * sin(theta) + y1;
  218.             numTries++;
  219.                 /* Measure distance between last two points; this will keep
  220.                    the triangles in the strip from being too long and thin */
  221.                 dist = sqrt((y2 - y1)*(y2 - y1) + (x2 - x1)*(x2 - x1));
  222.             } while ((x2 <= -1. || 1. <= x2 || y2 <= -1. || 1. <= y2 || 
  223.                      dist > distThreshold) && numTries < tenacity);
  224.             /* if it couldn't find a vertex, break out */
  225.             if (numTries == tenacity) break;
  226.             /* Store vertex in strip and rotate vertices */
  227.             *dst++ = x2;
  228.             *dst++ = y2;
  229.             x0 = x1;
  230.             y0 = y1;
  231.             x1 = x2;
  232.             y1 = y2;
  233.         }
  234.         if (i < end) {
  235.         /* Didn't finish the loop above, so we must have
  236.          * gotten stuck.  Better back up a vertex and
  237.          * try to turn the strip around.
  238.              */
  239.         if (firsttry == 1) {
  240.             firsttry = 0;
  241.             begin = i;
  242.         } 
  243.         if (begin < 1) {
  244.         /* We've worked our way to the begining of the
  245.          * strip, good time to give up on this one.
  246.          */
  247.                 free(strip);
  248.             free(winding);
  249.             return 0;
  250.         }
  251.         begin -= 1;
  252.         end = i + 1;
  253.         tenacity += 1000;
  254.         /* Back up to the beginth vertex */
  255.         dst = (strip + 4) + 2 * begin;
  256.         x0 = *(dst-4);
  257.         y0 = *(dst-3);
  258.         x1 = *(dst-2);
  259.         y1 = *(dst-1);
  260.         } else {
  261.         /* Success!  Turned around! Let's try to finish strip */
  262.         begin = i;
  263.         end = objsPerBgnEnd;
  264.         tenacity = maxTries;
  265.         }
  266.     } while (i < objsPerBgnEnd);
  267.     
  268.     free(winding);
  269.     return strip;
  270. }
  271.  
  272. void QuadStrip__Layout(VertexPtr thisVertex)
  273. {
  274.     QuadStripPtr this = (QuadStripPtr)thisVertex;
  275.     int windowDim = min(this->environ.windowWidth, this->environ.windowHeight);
  276.  
  277.     GLfloat ndcSize = this->size/(double)windowDim/(double)windowDim*4.0;
  278.     GLfloat width = sqrt(ndcSize/this->aspect);
  279.     GLfloat height = ndcSize/width;
  280.  
  281.     GLfloat *newTraversalData, *dst;
  282.  
  283.     int i, j;
  284.     GLfloat x, y;
  285.     GLfloat horz, vert;
  286.     int bounced = True;
  287.     int row = 0;
  288.     int step = 0;
  289.  
  290.     this->vertsPerBgnEnd = this->objsPerBgnEnd * this->vertsPerFacet + 2;
  291.     this->facetsPerBgnEnd = this->vertsPerBgnEnd/this->vertsPerFacet;
  292.     /* Allocate necessary data */
  293.     newTraversalData = (GLfloat*)malloc(this->numBgnEnds * this->vertsPerBgnEnd * 2 * sizeof(GLfloat));
  294.     CheckMalloc(newTraversalData);
  295.     dst = newTraversalData;
  296.  
  297.     if (this->orientation == Random) {
  298.     /* Choosing random orientation necessitates blowing off aspect ratios */
  299.     GLfloat *newStrip, *src;
  300.         /* Use Vertex__Layout() to get strip starting points*/
  301.         this->layoutPoints = this->numBgnEnds;
  302.         this->layoutPadding = sqrt(2.0*ndcSize);
  303.         this->layoutPadding += (1. + (this->antiAlias!=Off))/
  304.                            (float)windowDim;
  305.         Vertex__Layout(thisVertex);
  306.     src = this->traversalData;
  307.     mysrand(15000);
  308.         for (i=0; i<this->numBgnEnds; i++) {
  309.         /* Repeat strip walking until a legitimate one comes up */
  310.         const int maxTries = 10;
  311.         int numTries;
  312.         for (numTries = 0; 
  313.                  numTries < maxTries && 
  314.                  ((newStrip = LayoutRandomQStrip(this, src)) == 0);
  315.          numTries++);
  316.         if (numTries == maxTries) {
  317.          printf("GLperf: Error in Quad Strip creation\n");
  318.          exit(1);
  319.         }
  320.         /* Copy newStrip to traversalData */
  321.         memcpy(dst, newStrip, this->vertsPerBgnEnd * sizeof(GLfloat) * 2);
  322.         dst += this->vertsPerBgnEnd * 2;
  323.         free(newStrip);
  324.         src += 2;
  325.     }
  326.     free(this->traversalData);
  327.     } else {
  328.         for (i=0; i<this->numBgnEnds; i++) {
  329.             if (bounced) {
  330.                 x = -1.0;
  331.                 y = fmod(row * height, 2.0) - 1.0;
  332.                 horz = width;
  333.                 vert = height;
  334.                 bounced = False;
  335.                 if(y+vert > 1.0) {
  336.                     row+=2;
  337.                     y = fmod(row * height, 2.0) - 1.0;
  338.                 }
  339.                 row+=2;
  340.                 step = 0;
  341.             }
  342.             for (j=0; j<this->vertsPerBgnEnd; j++) {
  343.                 if (x+horz <= -1.0 || 1.0 <= x+horz) {
  344.                     horz *= -1.0;
  345.                     bounced = True;
  346.                 }
  347.                 if(step++ < 2) {
  348.                     y += vert;
  349.                     vert *= -1.0;
  350.                 } else {
  351.                     x += horz;
  352.                     y += vert;
  353.                     vert *= -1.0;
  354.                     step = 1;
  355.                 }
  356.                 if(this->orientation == Vertical) {
  357.                     *dst++ = y;
  358.                     *dst++ = x;
  359.                 } else {
  360.                     *dst++ = x;
  361.                     *dst++ = y;
  362.                 }
  363.             }
  364.         }
  365.     }
  366.     this->traversalData = newTraversalData;
  367. }
  368.